#ifdef _FNT_CACHE_THREAD_OPTIONS_H_

CacheThreadOptions* CacheThreadOptions::_instance{nullptr};
OptionsPage* OptionsPage::cacheThreadOptions() {
	return CacheThreadOptions::instance();
}

CacheThreadOptions::CacheThreadOptions():
	OptionsPage{"Cache", "Remote file cache settings"}, ctp{nullptr}
{
	auto options=Tracer::instance()->options();
	if(!options->getDouble("cache.size", &cacheSizeDef)) {
		cacheSizeDef=3.0;
	}
	if(!options->getInt("cache.jobsize.wait", &jobSizeWaitDef)) {
		jobSizeWaitDef=1;
	}
	if(!options->getInt("cache.jobsize.nowait", &jobSizeNoWaitDef)) {
		jobSizeNoWaitDef=1;
	}

	auto flayout=new QFormLayout{};
	layout()->addLayout(flayout, 0);
	layout()->addStretch(1);

	spinCacheSize=new QDoubleSpinBox{this};
	flayout->addRow("&Memory usage:", spinCacheSize);
	spinCacheSize->setDecimals(1);
	spinCacheSize->setMaximum(20); // XXX
	spinCacheSize->setMinimum(.5);
	spinCacheSize->setValue(cacheSizeDef);
	cacheSizeSet=cacheSizeDef;
	spinCacheSize->setSingleStep(.5);
	spinCacheSize->setSuffix("GiB");
	spinCacheSize->setToolTip("Set maximum amount of memory used for cacheing remote files.");
	connect(spinCacheSize, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this, &CacheThreadOptions::cacheSizeChanged);

	spinJobSizeWait=new QSpinBox{this};
	flayout->addRow("&Cache parallelism:", spinJobSizeWait);
	spinJobSizeWait->setMaximum(8);
	spinJobSizeWait->setMinimum(1);
	spinJobSizeWait->setValue(jobSizeWaitDef);
	jobSizeWaitSet=jobSizeWaitDef;
	spinJobSizeWait->setSingleStep(1);
	spinJobSizeWait->setToolTip("Set maximum number of simutanious remote file downloads.");
	connect(spinJobSizeWait, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &CacheThreadOptions::jobSizeWaitChanged);

	spinJobSizeNoWait=new QSpinBox{this};
	flayout->addRow("&Pre-cache parallelism:", spinJobSizeNoWait);
	spinJobSizeNoWait->setMaximum(8);
	spinJobSizeNoWait->setMinimum(0);
	spinJobSizeNoWait->setValue(jobSizeNoWaitDef);
	jobSizeNoWaitSet=jobSizeWaitDef;
	spinJobSizeNoWait->setSingleStep(1);
	spinJobSizeNoWait->setToolTip("Set maximum number of simutanious remote file pre-downloads.\nPre-downloading usually improves user experience by reducing waiting time.\nSetting this to 0 will disable pre-downloading.");
	connect(spinJobSizeNoWait, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &CacheThreadOptions::jobSizeNoWaitChanged);
}
CacheThreadOptions::~CacheThreadOptions() {
}

void CacheThreadOptions::attach(CacheThreadPriv* _ctp) {
	ctp=_ctp;
	if(ctp) {
		cacheSizeUsed=cacheSizeDef;
		ctp->max_size=cacheSizeUsed*1024*1024*1024;
		jobSizeWaitUsed=jobSizeWaitDef;
		ctp->job_size_wait=jobSizeWaitUsed;
		jobSizeNoWaitUsed=jobSizeNoWaitDef;
		ctp->job_size_nowait=jobSizeNoWaitUsed;
	}
}

void CacheThreadOptions::getState(bool* a, bool* b, bool* c, bool* d) const {
	*a=*b=ctp && !(cacheSizeSet==cacheSizeUsed && jobSizeWaitSet==jobSizeWaitUsed && jobSizeNoWaitSet==jobSizeNoWaitUsed);
	*c=*d=!(cacheSizeDef==cacheSizeSet && jobSizeWaitDef==jobSizeWaitSet && jobSizeNoWaitDef==jobSizeNoWaitSet);
}
void CacheThreadOptions::setStateImp(SessionState ts) {
}
void CacheThreadOptions::useDefaultImp() {
	if(cacheSizeSet!=cacheSizeDef)
		spinCacheSize->setValue(cacheSizeDef);
	if(jobSizeWaitSet!=jobSizeWaitDef)
		spinJobSizeWait->setValue(jobSizeWaitDef);
	if(jobSizeNoWaitSet!=jobSizeNoWaitDef)
		spinJobSizeNoWait->setValue(jobSizeNoWaitDef);
}
void CacheThreadOptions::saveDefaultImp() {
	auto options=Tracer::instance()->options();
	if(cacheSizeSet!=cacheSizeDef) {
		cacheSizeDef=cacheSizeSet;
		options->setDouble("cache.size", cacheSizeDef);
	}
	if(jobSizeWaitSet!=jobSizeWaitDef) {
		jobSizeWaitDef=jobSizeWaitSet;
		options->setInt("cache.jobsize.wait", jobSizeWaitDef);
	}
	if(jobSizeNoWaitSet!=jobSizeNoWaitDef) {
		jobSizeNoWaitDef=jobSizeNoWaitSet;
		options->setInt("cache.jobsize.nowait", jobSizeNoWaitDef);
	}
}
void CacheThreadOptions::applyChangesImp() {
	if(ctp) {
		std::unique_lock<std::mutex> lck{ctp->mtx_configs};
		if(cacheSizeSet!=cacheSizeUsed) {
			cacheSizeUsed=cacheSizeSet;
			ctp->max_size=cacheSizeUsed*1024*1024*1024;
		}
		if(jobSizeWaitSet!=jobSizeWaitUsed) {
			jobSizeWaitUsed=jobSizeWaitSet;
			ctp->job_size_wait=jobSizeWaitUsed;
		}
		if(jobSizeNoWaitSet!=jobSizeNoWaitUsed) {
			jobSizeNoWaitUsed=jobSizeNoWaitSet;
			ctp->job_size_nowait=jobSizeNoWaitUsed;
		}
	}
}
void CacheThreadOptions::resetChangesImp() {
	if(ctp) {
		if(cacheSizeSet!=cacheSizeUsed)
			spinCacheSize->setValue(cacheSizeUsed);
		if(jobSizeWaitSet!=jobSizeWaitUsed)
			spinJobSizeWait->setValue(jobSizeWaitUsed);
		if(jobSizeNoWaitSet!=jobSizeNoWaitUsed)
			spinJobSizeNoWait->setValue(jobSizeNoWaitUsed);
	}
}

void CacheThreadOptions::cacheSizeChanged(double v) {
	cacheSizeSet=v;
	notifyChange();
}
void CacheThreadOptions::jobSizeWaitChanged(int v) {
	jobSizeWaitSet=v;
	notifyChange();
}
void CacheThreadOptions::jobSizeNoWaitChanged(int v) {
	jobSizeNoWaitSet=v;
	notifyChange();
}

#endif
